package com.rongxue.service.utils;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rongxue.pojo.ObjectResult;
import com.rongxue.service.Impl.CashInAndOutServiceImpl;
import com.rongxue.service.shanbei.util.ConfigUtil;
import com.rongxue.service.shanbei.util.SignUtil;
import com.rongxue.utils.HttpClientUtil;
import com.rongxue.utils.RandomUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.util.*;


public class P2PMessageUtils {


    private static final String KEY = CashInAndOutServiceImpl.KEY;//密钥
    private static final String APP_KEY = CashInAndOutServiceImpl.APP_KEY ;//APP密钥
    private static final Logger LOGGER = LoggerFactory.getLogger(P2PMessageUtils.class);

    //发送报文,并将接收的报文装换成map,并验签
    public ObjectResult getDecXml(String url, String xml, int type){

        LOGGER.info("发送的报文========="+xml);
        //发送请求
        ObjectResult objectResult = new HttpClientUtil().sendPost(url, xml);
        LOGGER.info("接收的报文========"+objectResult.getStr());

        //请求成功时才会验签
        if (objectResult.getCode().equals("1")){

            Map<String, String> xmlElementMap = getXmlElementMap(objectResult.getStr());

            //验证身份证和验证银行卡的解析方式不一样
            if (type == 1){
                //身份证验签,只有返回成功时才会验签
                if (xmlElementMap.get("RESPONSECODE").equals("0000")) {
                    //验签
                    if (verificationSign(xmlElementMap)) {
                        return ObjectResult.build("1", "验签成功", xmlElementMap);
                    } else {
                        return ObjectResult.build("0", "验签失败");
                    }

                }else {
                    return ObjectResult.build("0",xmlElementMap.get("RESPONSEMSG"));
                }

            }else if (type == 2){
                //银行卡验签,只有返回成功时才会验签
                if (xmlElementMap.get("Rcd").equals("0000")) {

                    if (verificationBankSign(xmlElementMap)) {
                        return ObjectResult.build("1", "验签成功", xmlElementMap);
                    } else {
                        return ObjectResult.build("0", "验签失败");
                    }

                }else {
                    return ObjectResult.build("0", xmlElementMap.get("RDesc"));
                }

            }

        }else {
            return objectResult;
        }
        return ObjectResult.build("0","网络异常,请稍后重试");

    }


    //MD5工具类
    public String getMD5(String str) {
        String re = null;
        byte encrypt[];
        try {
            byte[] tem = str.getBytes();
            MessageDigest md5 = MessageDigest.getInstance("md5");
            md5.reset();
            md5.update(tem);
            encrypt = md5.digest();
            StringBuilder sb = new StringBuilder();
            for (byte t : encrypt) {
                String s = Integer.toHexString(t & 0xFF);
                if (s.length() == 1) {
                    s = "0" + s;
                }
                sb.append(s);
            }
            re = sb.toString();
            return re;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //接收的报文转map
    private Map<String, String> getXmlElementMap(String xmlFile){
        Map<String, String> map = new HashMap();
        Document document = null;
        try {
            document = DocumentHelper.parseText(xmlFile);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Element root = document.getRootElement();
        for (Iterator i = root.elementIterator(); i.hasNext(); ) {
            Element thre = (Element) i.next();
            map.put(thre.getName(), thre.getTextTrim());
        }
        return map;
    }


    //验证身份证签名
    private Boolean verificationSign( Map<String, String> xmlElementMap){
        StringBuffer sb = new StringBuffer();
        sb.append(xmlElementMap.get("VERSION"));
        sb.append("|");
        sb.append(xmlElementMap.get("RESPONSECODE"));
        sb.append("|");
        sb.append(xmlElementMap.get("RESPONSEMSG"));
        sb.append("|");
        sb.append(xmlElementMap.get("MCHNTORDERID"));
        sb.append("|");
        sb.append(KEY);
        String sign = getMD5(sb.toString());
        return sign.equals(xmlElementMap.get("SIGN"));
    }

    //验证银行卡签名
    private Boolean verificationBankSign( Map<String, String> xmlElementMap){
        StringBuffer sb = new StringBuffer();
        sb.append(xmlElementMap.get("Rcd"));
        sb.append("|");
        sb.append(xmlElementMap.get("OSsn"));
        sb.append("|");
        sb.append(xmlElementMap.get("CardNo"));
        sb.append("|");
        sb.append(xmlElementMap.get("MchntCd"));
        sb.append("|");
        sb.append(xmlElementMap.get("Ver"));
        sb.append("|");
        sb.append(KEY);
        String sign = getMD5(sb.toString());
        return sign.equals(xmlElementMap.get("Sign"));
    }
    //验证银行卡签名
    private boolean verificationOrderIdSign(Map<String, String> xmlElementMap) {
        StringBuffer sb = new StringBuffer();
        sb.append(xmlElementMap.get("RDesc"));
        sb.append("|");
        sb.append(xmlElementMap.get("Rcd"));
        sb.append("|");
        sb.append(xmlElementMap.get("OrderId"));
        sb.append("|");
        sb.append(KEY);
        String sign = getMD5(sb.toString());
        return sign.equals(xmlElementMap.get("Sign"));

    }

    //获取订单号
    public String getRechargeNo(String type){

        return type + System.nanoTime() + RandomUtil.getRandom(10).toString().substring(3);

    }

    //验证回调签名
    public ObjectResult verificationNotifySign(String TYPE, String VERSION, String RESPONSECODE, String RESPONSEMSG, String MCHNTCD, String MCHNTORDERID, String ORDERID,
                                               String AMT, String BANKCARD, String SIGN) {

        /**
         *
         TYPE+"|"+VERSION+"|"+RESPONSECODE+"|"+"MCHNTCD"+"|" + MCHNTORDERID+"|"+ORDERID"|"+AMT+"|"+BANKC ARD+"|"+"商户密钥"
         商户在接收到支付结果后需要对SIGN做验证
         *
         **/


        //响应码成功才验签
        if (RESPONSECODE.equals("0000")) {

            StringBuffer sb = new StringBuffer();
            sb.append(TYPE);
            sb.append("|");
            sb.append(VERSION);
            sb.append("|");
            sb.append(RESPONSECODE);
            sb.append("|");
            sb.append(MCHNTCD);
            sb.append("|");
            sb.append(MCHNTORDERID);
            sb.append("|");
            sb.append(ORDERID);
            sb.append("|");
            sb.append(AMT);
            sb.append("|");
            sb.append(BANKCARD);
            sb.append("|");
            sb.append(APP_KEY);

            String resultSign = getMD5(sb.toString());
            System.out.println(resultSign+"++++++++"+SIGN+"==========key"+KEY);
            if (resultSign.equals(SIGN)) {
                return ObjectResult.build("1", "验签成功");
            } else {
                return ObjectResult.build("0", "验签失败");
            }

        }else {
            return ObjectResult.build("0", RESPONSEMSG);
        }

    }

    //陕坝回调验签
    public  static Map<String,Object> sign(HttpServletRequest request, String str) throws Exception {
        Map<String,Object> data = new HashMap<>();
        request.setCharacterEncoding("UTF-8");//返回页面防止出现中文乱码

        BufferedReader reader = null;
        reader = new BufferedReader(new InputStreamReader(request.getInputStream()));//post方式传递读取字符流

        String jsonStr = null;
        StringBuilder result = new StringBuilder();

        while ((jsonStr = reader.readLine()) != null) {
            result.append(jsonStr);
        }

        reader.close();// 关闭输入流

        LOGGER.info(str+result.toString());//回调报文

        JSONObject jsonObject = JSON.parseObject(result.toString());
        data.put("jsonObject",jsonObject);
        Map<String,Object> map = (Map<String,Object>)JSON.parse(result.toString());

        if (!"RD000000".equals(jsonObject.get("code").toString())){
            LOGGER.info("msg:"+jsonObject.getString("msg"));
            data.put("flag",false);
            return data;
        }
        if(!SignUtil.signVerify(ConfigUtil.getPro("bank.key"),ConfigUtil.getPro("bank.secret"),map,jsonObject.getString("sign"))){
            LOGGER.info("msg:验签失败");
            data.put("flag",false);
            return data;
        }
        data.put("flag",true);
        return data;
    }
}
